Particle Set

Simulate trajectories of a particle cloud in a two-dimensional flow field. A doubly-periodic domain and randomly-generated flow fields are initially used. For additional documentation e.g. see : 1, 2, 3, 4

Exercises:

  • change the initial distribution of partices
  • increase the duration of the trajectories simulation
  • treat the non-periodic domain case by padding u,v with zeros
  • replace u,v with your own two-dimensional flow fields

particles in random flow

1. Import Software

using IndividualDisplacements, DataFrames
p=dirname(pathof(IndividualDisplacements))
include(joinpath(p,"../examples/flow_fields.jl"));

2. Flow Fields

A convenient way to set up the flow fields using the MeshArrays.jl package (which handles such staggered grids in general fashion) is to call the convert_to_FlowFields function with u,v arrays and time span as arguments.

u,v,ฯ•=random_flow_field()

๐น=convert_to_FlowFields(u,v,10.0);

In the above, the u,v arrays generated by random_flow_field can be replaced with any other pair provided by the user.

A couple of important considerations, however:

  • u,v are staggered on a C-grid; by -0.5 grid point in direction 1 for u (2 for v)

from the grid cell center (0.5,0.5)

  • u,v here derive from streamfunction ฯ•, defined at the corner point, which ensures that

the resulting u,v is non-divergent, purely rotational, over the C-grid domain. In brief:

u=-(circshift(ฯ•, (0,-1))-ฯ•)
v=(circshift(ฯ•, (-1,0))-ฯ•)

If user were to start with collocated velocity (uC,vC at the grid cell center) then one can easily obtain the staggered velocity (u,v) as follows. These may contain both rotational and divergent components.

u=0.5*(circshift(uC, (0,1))+uC)
v=0.5*(circshift(vC, (1,0))+vC)

3. Initialize Individuals

For example, we can initialize 100 particles within a central subdomain as follows.

np,nq=size(u)
x=np*(0. .+ 1.0*rand(1000))
y=nq*(0. .+ 1.0*rand(1000))
a=ones(size(x)); #subdomain array index (just 1 here)

The following constructor function wraps everything in the Individuals data structure.

๐ผ=Individuals(๐น,x,y,a)
  ๐Ÿ“Œ details     = (1, 1000) Array{Float64,1}
  ๐Ÿ”ด details     = (0, 5) ["ID", "x", "y", "fid", "t"]
  ๐Ÿ†” range       = (1, 1000)
  ๐Ÿš„ function    = dxy_dt!
  โˆซ  function    = default_solver
  ๐Ÿ”ง function    = postprocess_MeshArray
  ๐‘ƒ  details     = (:u0, :u1, :v0, :v1, :๐‘‡, :update_location!)

3. Compute Trajectories

The time period is ๐ผ.๐‘ƒ.๐‘‡ by default, unless โˆซ!(๐ผ,๐‘‡) is called instead.

โˆซ!(๐ผ)
1ร—1000 Array{Array{Float64,1},2}:
 [7.27738, 13.0045, 1.0]  [4.47776, 11.5454, 1.0]  โ€ฆ  [5.01068, 6.29591, 1.0]

4. Plot Results

For example, generate a simple animation:

p=dirname(pathof(IndividualDisplacements))
include(joinpath(p,"../examples/recipes_plots.jl"));

๐Ÿ”ด_by_t = groupby(๐ผ.๐Ÿ”ด, :t)
anim = @animate for t in eachindex(๐Ÿ”ด_by_t)
   phi_scatter(ฯ•,๐Ÿ”ด_by_t[t])
end

pth=tempdir()*"/"
gif(anim, pth*"RandomFlow.gif", fps = 10)

This page was generated using Literate.jl.